package org.asiainfo.ability.manager.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.asiainfo.ability.base.code.InstanceState;
import org.asiainfo.ability.base.utils.JsonUtils;
import org.asiainfo.ability.base.utils.StringUtils;
import org.asiainfo.ability.gateway.dao.ServiceDao;
import org.asiainfo.ability.gateway.model.Instance;
import org.asiainfo.ability.gateway.model.Machine;
import org.asiainfo.ability.manager.dao.PackageDao;
import org.asiainfo.ability.manager.model.JarPackage;
import org.asiainfo.ability.node.code.OperationType;
import org.asiainfo.ability.node.utils.HttpClient;
import org.asiainfo.ability.node.vo.NodeOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: visen
 * @Date: 2018/3/11
 * @Description:
 */
@Component
public class AgentService {

    private static final ObjectMapper mapper = new ObjectMapper();
    @Autowired
    private ServiceDao serviceDao;

    @Autowired
    private PackageDao packageDao;


    public Machine loadtMachine(long machineId) {
        return serviceDao.loadMachine(machineId);
    }

    public Instance loadtInstance(long id) {
        return serviceDao.loadInstance(id);
    }
    public void updateInstanceState(NodeOperation nodeOperation) {
        InstanceState state = null;
        if (nodeOperation.getType() == OperationType.start
                || nodeOperation.getType() == OperationType.resume) {
            state = InstanceState.active;
        } else if (nodeOperation.getType() == OperationType.shutdown ||
                nodeOperation.getType() == OperationType.forceShutdown) {
            state = InstanceState.shutdown;
        } else if (nodeOperation.getType() == OperationType.pause
                || nodeOperation.getType() == OperationType.silentStart) {
            state = InstanceState.pause;
        }
        if (state != null) {
            serviceDao.updateInstanceState(Long.parseLong(nodeOperation.getId()), state);
        }

    }

    public Machine fillNodeOperation(NodeOperation nodeOperation) {
        Instance instance = serviceDao.loadInstance(Long.parseLong(nodeOperation.getId()));
        Machine machine = serviceDao.loadMachine(Long.parseLong(instance.getMachineId()));
        JarPackage jarPackage = packageDao.loadPackage(Long.parseLong(instance.getRepoId()));
        nodeOperation.setServiceName(instance.getServiceName());
        nodeOperation.setIp(machine.getIp());
        nodeOperation.setPort(instance.getPort());
        nodeOperation.setPath(new StringBuilder(instance.getServiceName())
                .append(File.separator).append(instance.getBranch())
                .append(File.separator).append(instance.getVersion())
                .append(File.separator).toString());
        nodeOperation.setJarName(jarPackage.getJarName());
        nodeOperation.setBranch(instance.getBranch());
        return machine;
    }


    public String restartInstance(Machine machine, Instance instance, JarPackage jarPackage) {

        String ip = machine.getIpAddress();
        int ix = ip.indexOf(":");
        if (ix > -1) {
            ip = ip.substring(0, ix + 1);
        }
        StringBuilder url = new StringBuilder("http://")
                .append(machine.getIpAddress())
                .append("/manage");
        NodeOperation nodeOperation = new NodeOperation();
        nodeOperation.setType(OperationType.restart);
        nodeOperation.setPort(instance.getPort());
        nodeOperation.setServiceName(instance.getServiceName());
        nodeOperation.setIp(ip);
        nodeOperation.setPath(jarPackage.getJarName());
        CloseableHttpClient httpClient = HttpClient.createHttpClient(0, 5000);
        try {
            HttpPost httpPost = new HttpPost(url.toString());
            StringEntity entity = new StringEntity(mapper.writeValueAsString(nodeOperation)
                    , "utf-8");
            entity.setContentEncoding("utf-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);

            HttpResponse resp = httpClient.execute(httpPost);
            return EntityUtils.toString(resp.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            return "0";
        }

    }
    public static class BatchOperation {
        private OperationType action;
        private List data;

        public OperationType getAction() {
            return action;
        }

        public void setAction(OperationType action) {
            this.action = action;
        }

        public List<String> getData() {
            return data;
        }

        public void setData(List data) {
            this.data = data;
        }
    }

    public List processNode(BatchOperation batchOperation) throws Exception {
        CloseableHttpClient httpClient = HttpClient.createHttpClient(0, 3000);
        List result = new ArrayList();
        for (String instanceId : batchOperation.getData()) {
            NodeOperation nodeOperation = new NodeOperation();
            nodeOperation.setType(batchOperation.getAction());
            nodeOperation.setId(instanceId);

            Machine machine = fillNodeOperation(nodeOperation);
            if (machine == null) {
                result.add("0");
                continue;
            }

            StringBuilder url = new StringBuilder("http://");
            url.append(machine.getIpAddress());
            try {
                url.append("/manage");
                HttpPost httpPost = new HttpPost(url.toString());
                StringEntity entity = new StringEntity(JsonUtils.toJSON(nodeOperation), "utf-8");
                entity.setContentEncoding("utf-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
                HttpResponse resp = httpClient.execute(httpPost);
                if (StringUtils.isBlank(EntityUtils.toString(resp.getEntity()))) {
                    updateInstanceState(nodeOperation);
                    result.add("1");
                } else {
                    result.add("0");
                }

            } catch (Exception e) {
                e.printStackTrace();
                result.add("0");
            }
        }
        httpClient.close();
        return result;
    }
}
